package kamailio

import (
	"fmt"
	"net"
	"time"
)

// Client Kamailio API客户端
type Client struct {
	Host     string
	Port     int
	Username string
	Password string
}

// NewClient 创建新的Kamailio客户端
func NewClient(host string, port int, username, password string) *Client {
	return &Client{
		Host:     host,
		Port:     port,
		Username: username,
		Password: password,
	}
}

// SendCommand 发送命令到Kamailio
func (c *Client) SendCommand(cmd string) (string, error) {
	conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", c.Host, c.Port), 5*time.Second)
	if err != nil {
		return "", fmt.Errorf("failed to connect to Kamailio: %w", err)
	}
	defer conn.Close()

	// 设置读写超时
	conn.SetDeadline(time.Now().Add(10 * time.Second))

	// 发送认证信息
	authCmd := fmt.Sprintf("AUTH %s %s\n", c.Username, c.Password)
	if _, err := conn.Write([]byte(authCmd)); err != nil {
		return "", fmt.Errorf("failed to send auth: %w", err)
	}

	// 读取认证响应
	buf := make([]byte, 1024)
	n, err := conn.Read(buf)
	if err != nil {
		return "", fmt.Errorf("failed to read auth response: %w", err)
	}

	authResp := string(buf[:n])
	if authResp != "200 OK\n" {
		return "", fmt.Errorf("auth failed: %s", authResp)
	}

	// 发送命令
	if _, err := conn.Write([]byte(cmd + "\n")); err != nil {
		return "", fmt.Errorf("failed to send command: %w", err)
	}

	// 读取命令响应
	n, err = conn.Read(buf)
	if err != nil {
		return "", fmt.Errorf("failed to read command response: %w", err)
	}

	return string(buf[:n]), nil
}

// GetUsers 获取所有注册用户
func (c *Client) GetUsers() (string, error) {
	return c.SendCommand("ul show")
}

// AddUser 添加用户
func (c *Client) AddUser(username, password string) error {
	cmd := fmt.Sprintf("ul add %s %s", username, password)
	_, err := c.SendCommand(cmd)
	return err
}

// RemoveUser 删除用户
func (c *Client) RemoveUser(username string) error {
	cmd := fmt.Sprintf("ul rm %s", username)
	_, err := c.SendCommand(cmd)
	return err
}

// GetStatistics 获取统计信息
func (c *Client) GetStatistics(module string) (string, error) {
	cmd := fmt.Sprintf("stats get %s", module)
	return c.SendCommand(cmd)
}

// ReloadConfig 重新加载配置
func (c *Client) ReloadConfig() error {
	_, err := c.SendCommand("reload")
	return err
}

// Ping 测试连接
func (c *Client) Ping() error {
	_, err := c.SendCommand("ping")
	return err
}